package com.intel.factorytest.cfparser.concrete;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

import com.intel.factorytest.util.SDCardUtil;
import com.intel.factorytest.R;

import android.content.Context;
import android.content.res.AssetManager;
import android.util.Log;

public abstract class AConfigFileParser {
    
    public static final String EXTENSION_NONE = "";
    public static final String EXTENSION_PROPERTISE = "properties";
    public static final String EXTENSION_XML = "xml";
    public static final String PREFERENC_NAME="case_config";
    
    private static final String config_data = "mat_test_case_config.properties"; 
    private static final String config_data_for_pcba = "mat_test_case_config_for_pcba.properties"; 
    private static final String sep = System.getProperty("file.separator", "/");
    
    private String[] storageList;
    protected Context context;
    private String internalStoragePath = "";
    private String externalStoragePath = "";
    
    protected AConfigFileParser(Context context) {
        this.context = context;
        initStoragePath();
    }
    
    private void initStoragePath() {
        storageList = SDCardUtil.getStorageList(context);
        if (storageList != null) {
            for (String storageDir : storageList) {
                if (storageDir.contains("emulated")) {
                    internalStoragePath = storageDir;
                } else if (storageDir.contains("sdcard1")) {
                    externalStoragePath = storageDir;
                } else {
                    // do nothing
                }
            }
        }
    }
    
//    private static AConfigFileParser getInstance(Context context, String extension) {
//        String fileExt = getConfigFileExtension(extension);
//        if (fileExt == null || fileExt.trim().length() == 0) {
//            return new NoneExtensionConfParser(context);
//        } else if (fileExt.equals(EXTENSION_PROPERTISE)) {
//            return new PropertiesConfParser(context);
//        } else if (fileExt.equals(EXTENSION_XML)) {
//            // TODO
//            return null;
//        } else {
//            return null;
//        }
//    }
    
    /**
     * 
     * @param isSys 鏄惁鏄郴缁熺骇娴嬭瘯--(鍏ㄦ祴璇曞拰鏉挎満娴嬭瘯)
     * @param isSysForPcba 鏄惁鏄澘鏈烘祴锟�
     * @param localeString 鏈湴璇█
     * @param sdPath sdcard璺緞
     * @return
     */
    public List<Map<String, Object>> doParse(int isSys, int isSysForPcba, String localeString, String sdPath) {
        
        System.out.println("tangjun AConfigFileParser::doParse: sdPath=" + sdPath);
        boolean isPcba = isSysForPcba == 1 ? true : false;
        
        InputStream in = loadConfigFile(isPcba);
        
        return readConfigFile(in, isSys, isSysForPcba,localeString, sdPath);
    }

public void doParseCaseItem(int isSys, int isSysForPcba, String localeString, String sdPath) {
        
        System.out.println("tangjun AConfigFileParser::doParse: sdPath=" + sdPath);
        boolean isPcba = isSysForPcba == 1 ? true : false;
        
        InputStream in = loadCaseItemConfigFile(isPcba);
        if (in == null) {
            return;
        }
        readConfigFile(in, isSys, isSysForPcba,localeString, sdPath);
    }
    abstract protected List<Map<String, Object>> readConfigFile(InputStream in, int isSys, int isSysForPcba, String localeString, String sdPath);
    
    protected InputStream loadConfigFile(boolean isPcba) {
        InputStream in = null;
        if ((in = loadFromExternalCard(isPcba)) == null) {
            Log.d("cittest", "wangsm external============");
            if ((in = loadFromInternalCard(isPcba)) == null) {
                //in = loadFromAsset(isPcba);
                Log.d("cittest", "wangsm Internal============");
                in = loadFromRaw(isPcba);
            }
        }
        return in;
    }

    protected InputStream loadCaseItemConfigFile(boolean isPcba) {
//        InputStream in = null;
//        if ((in = loadFromExternalCard(isPcba)) == null) {
//            if ((in = loadFromInternalCard(isPcba)) == null) {
//                in = loadFromAsset(isPcba);
//            }
//        }
        return loadFromEtc(isPcba);
    }

    private InputStream loadFromExternalCard(boolean isPcba) {
        String externalPath = getExternalStorageDirectory(StorageType.EXTERNAL);
        Log.i("tangjun: AConfigFileParser::loadFromExternalCard: externalPath = ", externalPath);

        return openFile(isPcba, externalPath);
    }
    private InputStream loadFromEtc(boolean isPcba) {
        String externalPath = "/system/etc/mat_config.xml";
        Log.i("tangjun: AConfigFileParser::loadFromExternalCard: externalPath = ", externalPath);
        File configFile = new File(externalPath);
        if (configFile.exists()) {
            try {
                return new FileInputStream(configFile);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    private InputStream loadFromInternalCard(boolean isPcba) {
        String internalPath = getExternalStorageDirectory(StorageType.INTERNAL);
        Log.i("tangjun: AConfigFileParser::loadFromInternalCard: internalPaht = ", internalPath);

        return openFile(isPcba, internalPath);
    }
    
    private InputStream openFile(boolean isPcba, String storagePath) {
        if (storagePath == null || storagePath.trim().length() == 0) {
            return null;
        }
        File confFile = null;
        if (isPcba) {
            confFile = new File(storagePath + sep + config_data_for_pcba);
        } else {
            confFile = new File(storagePath + sep + config_data);
        }
        if (confFile.exists()) {
            try {
                return new FileInputStream(confFile);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return null;
    }
    
    private InputStream loadFromAsset(boolean isPcba) {
        InputStream in = null;
        try {
            AssetManager am = context.getResources().getAssets();
            String[] fileNames = am.list("");
            if (isPcba) {
                for (String fn : fileNames) {
                    if (fn.equals(config_data_for_pcba)) {
                        in = am.open(config_data_for_pcba);
                        break;
                    }
                }
            } else {
                for (String fn : fileNames) {
                    if (fn.equals(config_data)) {
                        in = am.open(config_data);
                        break;
                    }
                }
            }
        } catch (IOException e) {
            // TODO: handle exception
        }
        return in;
    }

    private InputStream loadFromRaw(boolean isPcba) {
        InputStream in = null;
        try {
            if (isPcba) {
                in = context.getResources().openRawResource(R.raw.mat_test_case_config_for_pcba);
            } else {
                in = context.getResources().openRawResource(R.raw.mat_test_case_config);
            }
        } catch (Exception e) {
            // TODO: handle exception
        }
        return in;
    }    
    /**
     * get the extension name of files which under this directory and the name start with "mat_test_case_config"
     * 
     * @param dirPath directory path
     * @return
     */
//    private static String getConfigFileExtension(String extension) {
//        String ext = null;
//        
//        if (extension.equals(EXTENSION_XML)) {
//            ext = EXTENSION_XML;
//        } else if (extension.equals(EXTENSION_PROPERTISE)) {
//            ext = EXTENSION_PROPERTISE;
//        } else {
//            ext = EXTENSION_NULL;
//        }
//            
//        return ext;
//    }
    
    private String getExternalStorageDirectory(StorageType type) {
        // storageList = [/storage/emulated/0, /storage/sdcard1, /storage/usbcard1]
        
        String storageDir = null;
        switch (type) {
        case EXTERNAL:
            storageDir = externalStoragePath;
            break;
        case INTERNAL:
            storageDir = internalStoragePath;
            break;

        default:
            break;
        }
        
        return storageDir;
    }
    
    private enum StorageType { EXTERNAL, INTERNAL }
}
